package com.deyuanyun.pic.ctrl.service.impl;

import com.deyuanyun.pic.common.util.ObjectUtil;
import com.deyuanyun.pic.common.util.StringUtils;
import com.deyuanyun.pic.common.util.web.Asserts;
import com.deyuanyun.pic.ctrl.controller.vo.CpProtectionParamExpandVO;
import com.deyuanyun.pic.ctrl.controller.vo.CpProtectionParamQueryVO;
import com.deyuanyun.pic.ctrl.controller.vo.CpSegmentExpandVO;
import com.deyuanyun.pic.ctrl.controller.vo.CpSegmentPlanVO;
import com.deyuanyun.pic.ctrl.controller.vo.ProtectionParamDateVO;
import com.deyuanyun.pic.ctrl.domain.CpProtectionParam;
import com.deyuanyun.pic.ctrl.domain.CpSegment;
import com.deyuanyun.pic.ctrl.domain.CpSegmentExample;
import com.deyuanyun.pic.ctrl.domain.CpStandard;
import com.deyuanyun.pic.ctrl.enumeration.OperationStandard;
import com.deyuanyun.pic.ctrl.enumeration.PlanEndMode;
import com.deyuanyun.pic.ctrl.enumeration.PlanInspectionFrequency;
import com.deyuanyun.pic.ctrl.mapper.CpProtectionParamMapper;
import com.deyuanyun.pic.ctrl.mapper.CpSegmentMapper;
import com.deyuanyun.pic.ctrl.mapper.CpStandardMapper;
import com.deyuanyun.pic.ctrl.mapper.OperationPlanMapper;
import com.deyuanyun.pic.ctrl.service.OperationPlanService;
import com.deyuanyun.pic.ctrl.task.CtrlPlanConsts;
import com.deyuanyun.pic.ctrl.task.PipeLineStandardTask;
import com.deyuanyun.pic.ctrl.task.VavleRoomStandardTask;
import com.deyuanyun.pic.ctrl.task.domain.PipeLineStandard;
import com.deyuanyun.pic.ctrl.task.domain.ScheduleDto;
import com.deyuanyun.pic.ctrl.task.domain.StandardPlan;
import com.deyuanyun.pic.ctrl.task.domain.ValveRoomStandard;
import com.deyuanyun.pic.pipe.domain.PipeLineElement;
import com.deyuanyun.pic.pipe.domain.PipeLineElementExample;
import com.deyuanyun.pic.pipe.mapper.PipeLineElementMapper;
import com.deyuanyun.pic.settings.controller.pipe.vo.PipeLocationDTO;
import com.deyuanyun.pic.settings.domain.pipe.PipeLine;
import com.deyuanyun.pic.settings.domain.util.DomainInitUtil;
import com.deyuanyun.pic.settings.service.pipe.PipeLocationService;
import com.deyuanyun.pic.settings.support.utils.BaseCodeUtils;
import com.deyuanyun.pic.settings.support.utils.PipeDictUtils;
import com.deyuanyun.pic.settings.task.SchedulerJob;
import com.deyuanyun.pic.settings.task.util.QuartzManagerUtil;
import com.deyuanyun.pic.settings.task.util.TaskCalendarUtil;
import com.google.common.base.Objects;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormat;
import org.quartz.DateBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 阴保运行计划service接口实现类
 *
 * @author axiao(xj08.dream@gmail.com)
 * @version 1.0
 *          Histroy: [修改人][时间][描述]
 * @date 2016-09-08
 */
@Service
public class OperationPlanServiceImpl implements OperationPlanService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OperationPlanServiceImpl.class);

    private
    @Autowired
    CpSegmentMapper cpSegmentMapper;

    private
    @Autowired
    CpProtectionParamMapper cpProtectionParamMapper;

    private
    @Autowired
    OperationPlanMapper operationPlanMapper;

    private
    @Autowired
    PipeLocationService pipeLocationService;

    private
    @Autowired
    CpStandardMapper cpStandardMapper;

    private
    @Autowired
    PipeLineElementMapper pipeLineElementMapper;



    private static final String PIPE_LINE_STR = "PIPELINE";

    private static final String VAVLE_ROOR_STR = "VALVEROOM";

    @Override
    public void saveOrReleasePlan(CpSegmentExpandVO cpSegmentExpandVO, boolean isRelease) {
        try {
            boolean isPipeOrValve = false; //默认为场站阀室
            if (Objects.equal(PIPE_LINE_STR, cpSegmentExpandVO.getApplyTo())) { //管线交叉判断
                isPipeOrValve = true; //管线

                //queryCrossOverlap(cpSegmentExpandVO.getPipeLineId(), cpSegmentExpandVO.getFromPointMileage(), cpSegmentExpandVO.getToPointMileage());
            }

            //保存之前先把以前的给干掉
            CpSegment cpSegment = getCpSegment(cpSegmentExpandVO);
            if (cpSegment != null) {
                String dataStated = cpSegment.getDataStated();
                List<CpProtectionParamExpandVO> protectionParams = operationPlanMapper.queryParamByQueryVO(new CpProtectionParamQueryVO().setCpSegmentId(cpSegment.getId()));

                deleteYBPlan(cpSegment, dataStated, protectionParams);
            }

            if (PIPE_LINE_STR.equals(cpSegmentExpandVO.getApplyTo())) {
                PipeLocationDTO fromLocation = pipeLocationService.queryPipeLocationById(cpSegmentExpandVO.getPipeLineId(), cpSegmentExpandVO.getFromPointId());
                if (fromLocation != null) {
                    cpSegmentExpandVO.setFromPointType(fromLocation.getType());
                }
                PipeLocationDTO toLocation = pipeLocationService.queryPipeLocationById(cpSegmentExpandVO.getPipeLineId(), cpSegmentExpandVO.getToPointId());
                if (toLocation != null) {
                    cpSegmentExpandVO.setToPointType(toLocation.getType());
                }
            }

            setDeletedAndNew(cpSegmentExpandVO, 0, 0);

            String use = cpSegmentExpandVO.getUse();

            DomainInitUtil.initCreateDomain(cpSegmentExpandVO);
            String segmentId = cpSegmentExpandVO.getId();
            cpSegmentMapper.insertSelective(cpSegmentExpandVO);

            List<CpProtectionParamExpandVO> expandVOs = cpSegmentExpandVO.getProParams();
            for (int i = 0, len = expandVOs.size(); i < len; i++) {
                CpProtectionParamExpandVO protectionParam = expandVOs.get(i);
                DomainInitUtil.initCreateDomain(protectionParam);
                String protectionParamId = protectionParam.getId();

                protectionParam.setCpSegmentId(segmentId);
                setDeletedAndNew(protectionParam, 0, 0);
                cpProtectionParamMapper.insertSelective(protectionParam);

                if (OperationStandard.CUSTOM.name().equals(use)) {
                    CpStandard cpStandard = new CpStandard();
                    DomainInitUtil.initCreateDomain(cpStandard);
                    cpStandard.setName(use);
                    cpStandard.setProtectionObjectId(protectionParamId);
                    cpStandard.setDeviceObject(protectionParam.getDeviceObject());
                    cpStandard.setDeviceItem(protectionParam.getDeviceParam());
                    cpStandard.setFrequency(protectionParam.getFrequency());

                    setDeletedAndNew(cpStandard, 0, 0);
                    cpStandardMapper.insertSelective(cpStandard);
                }
            }

            if (isRelease) { //等于发布的时候，会建立任务
                ybPlanCreate(cpSegmentExpandVO, isPipeOrValve);
            }
        } catch (Exception e) {
            LOGGER.error("在保存或者发布管线任务的时候出错", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除阴保任务
     *
     * @param cpSegment
     * @param dataStated       只有在为20的时候才会删除任务
     * @param protectionParams
     */
    private void deleteYBPlan(CpSegment cpSegment, String dataStated, List<CpProtectionParamExpandVO> protectionParams) {
        List<JobKey> keys = new ArrayList<JobKey>();

        cpSegmentMapper.deleteByPrimaryKey(cpSegment.getId());

        List<String> cpProIds = new ArrayList<String>(); //阴保设施保护参数id集合，用于自定义标准删除信息
        for (int i = 0, len = protectionParams.size(); i < len; i++) {
            CpProtectionParamExpandVO protectionParam = protectionParams.get(i);
            cpProtectionParamMapper.deleteByPrimaryKey(protectionParam.getId());

            if (OperationStandard.CUSTOM.name().equals(cpSegment.getUse())) {
                cpProIds.add(protectionParam.getId());
            }

            if ("20".equals(dataStated)) {
                if (StringUtils.isNotEmpty(protectionParam.getFrequency()) && protectionParam.getBeginPlanDate() != null) {
                    JobKey jobKey = getJobKeys(protectionParam, cpSegment.getPipeLineId(), cpSegment.getFromPointId(), cpSegment.getToPointId(), true);
                    if (jobKey != null) {
                        keys.add(jobKey);
                    }
                }
            }
        }
        if (!cpProIds.isEmpty())
            operationPlanMapper.deleteCpStandard(cpProIds);
        if (!keys.isEmpty())
            QuartzManagerUtil.removeJob(keys);//删除创建好的任务
    }

    /**
     * 获取阴保任务JobKey
     *
     * @param protectionParam
     * @param pipeLineId      管道id
     * @param fromId          起点位置id
     * @param toId            终点位置id
     * @param showValve       是否获取场站阀室的JobKey
     * @return
     */
    private JobKey getJobKeys(CpProtectionParamExpandVO protectionParam, String pipeLineId, String fromId, String toId, boolean showValve) {
        String jobName = "";
        String jobGroupName = CtrlPlanConsts.STANDARD_PLAN_GROUP_NAME;

        String deviceObjectId = protectionParam.getDeviceObject();
        String deviceParamId = protectionParam.getDeviceParam();
        String deviceObjectName = BaseCodeUtils.getName(deviceObjectId);
        String deviceParamName = BaseCodeUtils.getName(deviceParamId);

        if (deviceObjectName != null) {
            jobName += deviceObjectName;
        }
        if (deviceParamName != null) {
            jobName += deviceParamName;
        }

        if (Objects.equal(PIPE_LINE_STR, protectionParam.getApplyTo())) {
            String pipeJobName = ""; //每一个单独的任务
            PipeLine pipeLine = PipeDictUtils.getLineById(pipeLineId);
            if (StringUtils.isNotEmpty(pipeLine.getName())) {
                pipeJobName += pipeLine.getName();
            }

            PipeLocationDTO fromDTO = pipeLocationService.queryPipeLocationById(pipeLineId, fromId);
            PipeLocationDTO toDTO = pipeLocationService.queryPipeLocationById(pipeLineId, toId);

            if (fromDTO != null) {
                pipeJobName += fromDTO.getName();
            }
            if (toDTO != null) {
                pipeJobName += toDTO.getName();
            }
            pipeJobName += jobName;

            //使用hex-encoded过后的jobName
            return JobKey.jobKey(new Md5Hash(pipeJobName).toHex(), jobGroupName + CtrlPlanConsts.PIPE_LINE_STANDARD_GROUP_NAME);

        } else if (Objects.equal(VAVLE_ROOR_STR, protectionParam.getApplyTo()) && showValve) {
            //使用hex-encoded过后的jobName
            return JobKey.jobKey(new Md5Hash(jobName).toHex(), jobGroupName + CtrlPlanConsts.VALVE_ROOM_STANDARD_GROUP_NAME);
        }

        return null;
    }

    private void setFieldValue(Object obj, String fieldName, Object value) {
        Field field = ReflectionUtils.findField(obj.getClass(), fieldName);
        field.setAccessible(true);
        ReflectionUtils.setField(field, obj, value);
    }

    private void setDeletedAndNew(Object obj, int deleted, int isNewest) {
        setFieldValue(obj, "deleted", (short) deleted);
        setFieldValue(obj, "isNewest", (short) isNewest);
    }

    /**
     * 重建阴保计划的所有任务
     *
     * @param cpSegmentExpandVO
     * @param isPipeOrValve     是管线还是场站阀室,true为管线，false为场站阀室
     * @throws Exception
     */
    private void ybPlanCreate(CpSegmentExpandVO cpSegmentExpandVO, boolean isPipeOrValve) throws Exception {

        PipeLocationDTO fromLocation = null, toLocation = null;

        String pipeLineId = cpSegmentExpandVO.getPipeLineId();

        String use = cpSegmentExpandVO.getUse();
        String fromId = cpSegmentExpandVO.getFromPointId();
        String toId = cpSegmentExpandVO.getToPointId();

        if (isPipeOrValve) { //是管线的时候组装任务名
            fromLocation = pipeLocationService.queryPipeLocationById(pipeLineId, fromId);
            toLocation = pipeLocationService.queryPipeLocationById(pipeLineId, toId);
        }

        List<SchedulerJob> schedulerJobs = new ArrayList<SchedulerJob>();

        List<CpProtectionParamExpandVO> expandVOs = cpSegmentExpandVO.getProParams();
        for (int i = 0, len = expandVOs.size(); i < len; i++) {
            CpProtectionParamExpandVO protectionParam = expandVOs.get(i);

            Date beginDate = protectionParam.getBeginPlanDate();//开始时间
            String frequency = protectionParam.getFrequency(); //检测频率

            if (StringUtils.isNotEmpty(frequency) && beginDate != null) {

                protectionParam.setApplyTo(cpSegmentExpandVO.getApplyTo());
                JobKey jobKey = getJobKeys(protectionParam, pipeLineId, fromId, toId, true);

                String alertAdvanceTime = protectionParam.getAlertAdvanceTime();//提前触发时间

                Date endDate = protectionParam.getEndDate();//结束时间
                Integer endCount = protectionParam.getEndCount();//结束次数

                PlanEndMode planEndMode = PlanEndMode.getInstance(protectionParam.getEndMode());//结束方式

                if (PlanEndMode.COUNT.equals(planEndMode)) {
                    Asserts.assertTrue(endCount != null || endCount != 0, "结束次数不能为空且不能为零！");
                } else if (PlanEndMode.DATE.equals(planEndMode)) {
                    Asserts.assertTrue(endDate != null, "结束时间不能为空！");
                }

                Asserts.assertTrue(StringUtils.isNotEmpty(alertAdvanceTime), "提前触发时间不能为空!");

                PlanInspectionFrequency planInspectionFrequency = PlanInspectionFrequency.getInstance(frequency);

                DateBuilder.IntervalUnit intervalUnit = null;
                int timeInterval = 0;
                if (PlanInspectionFrequency.ANNUALLY.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.YEAR;
                    timeInterval = 1;
                } else if (PlanInspectionFrequency.MONTHLY.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.MONTH;
                    timeInterval = 1;
                } else if (PlanInspectionFrequency.TWO_MONTH.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.MONTH;
                    timeInterval = 2;
                } else if (PlanInspectionFrequency.THREE_MONTH.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.MONTH;
                    timeInterval = 3;
                } else if (PlanInspectionFrequency.SIX_MONTH.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.MONTH;
                    timeInterval = 6;
                } else if (PlanInspectionFrequency.WEEKLY.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.WEEK;
                    timeInterval = 1;
                } else if (PlanInspectionFrequency.TWO_WEEK.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.WEEK;
                    timeInterval = 2;
                } else if (PlanInspectionFrequency.EVERY_DAY.equals(planInspectionFrequency)) {
                    intervalUnit = DateBuilder.IntervalUnit.DAY;
                    timeInterval = 1;
                } else {
                    intervalUnit = DateBuilder.IntervalUnit.HOUR;
                    timeInterval = 1;
                }

                LocalTime time = LocalTime.parse(alertAdvanceTime, DateTimeFormat.forPattern("HH:mm"));
                int hour = time.getHourOfDay();
                int minute = time.getMinuteOfHour();
                beginDate = LocalDateTime.fromDateFields(beginDate).withTime(hour, minute, 0, 0).toDate();

                StandardPlan standardPlan = new StandardPlan();
                String deviceObjectId = protectionParam.getDeviceObject();
                String deviceParamId = protectionParam.getDeviceParam();
                String id = protectionParam.getId();

                standardPlan.setId(id);
                standardPlan.setDeviceObject(deviceObjectId);
                standardPlan.setDeviceObjectName(BaseCodeUtils.getName(deviceObjectId));
                standardPlan.setDeviceParam(deviceParamId);
                standardPlan.setDeviceParamName(BaseCodeUtils.getName(deviceParamId));
                standardPlan.setFrequency(planInspectionFrequency.toString());
                standardPlan.setUse(use);
                standardPlan.setBeginPlanDate(protectionParam.getBeginPlanDate());
                standardPlan.setAlertAdvanceTime(alertAdvanceTime);
                standardPlan.setAlertMode(protectionParam.getAlertMode());
                standardPlan.setAlertAdvanceCount(protectionParam.getAlertAdvanceCount());

                if (isPipeOrValve) {
                    PipeLineStandard pipeLineStandard = new PipeLineStandard();
                    BeanUtils.copyProperties(standardPlan, pipeLineStandard);

                    pipeLineStandard.setPipeLineId(pipeLineId);
                    pipeLineStandard.setFromPointId(fromLocation.getId());
                    pipeLineStandard.setFromPointMileage(fromLocation.getMileage2());
                    pipeLineStandard.setFromPointType(fromLocation.getType());

                    pipeLineStandard.setToPointId(toLocation.getId());
                    pipeLineStandard.setToPointMileage(toLocation.getMileage2());
                    pipeLineStandard.setToPointType(toLocation.getType());

                    Map<String, Object> dataMap = new HashMap<String, Object>();
                    dataMap.put(StandardPlan.class.getName(), pipeLineStandard);
                    SchedulerJob schedulerJob = new SchedulerJob(jobKey.getName(), jobKey.getGroup(), beginDate,
                            endDate, PipeLineStandardTask.class, endCount, intervalUnit, timeInterval, dataMap);

                    schedulerJobs.add(schedulerJob);
                } else {
                    ValveRoomStandard valveRoomStandard = new ValveRoomStandard();
                    BeanUtils.copyProperties(standardPlan, valveRoomStandard);
                    Map<String, Object> dataMap = new HashMap<String, Object>();
                    dataMap.put(StandardPlan.class.getName(), valveRoomStandard);
                    SchedulerJob schedulerJob = new SchedulerJob(jobKey.getName(), jobKey.getGroup(), beginDate,
                            endDate, VavleRoomStandardTask.class, endCount, intervalUnit, timeInterval, dataMap);

                    schedulerJobs.add(schedulerJob);
                }
            }
        }
        if (!schedulerJobs.isEmpty()) {
            for (int i = 0, len = schedulerJobs.size(); i < len; i++) {
                QuartzManagerUtil.addCalendarJob(schedulerJobs.get(i)); //添加任务
            }
        }
    }

    @Override
    public ProtectionParamDateVO savePlan(CpSegmentExpandVO cpSegmentExpandVO) {
        ProtectionParamDateVO dateVO = null;

        CpSegment cpSegment = getCpSegment(cpSegmentExpandVO);
        String use = cpSegmentExpandVO.getUse();
        List<CpProtectionParamExpandVO> newParamExpandVOs = cpSegmentExpandVO.getProParams(); //页面传入的新值

        if (newParamExpandVOs == null || newParamExpandVOs.isEmpty()) {
            return null;
        }

        if (cpSegment != null) {
            String cpSegmentId = cpSegment.getId();
            List<CpProtectionParamExpandVO> oldCpProtectionParams = new ArrayList<CpProtectionParamExpandVO>();
            for (int i = 0, len = newParamExpandVOs.size(); i < len; i++) {
                CpProtectionParam newCpProParam = newParamExpandVOs.get(i);
                String deviceObject = newCpProParam.getDeviceObject();
                String deviceItem = newCpProParam.getDeviceParam();

                CpProtectionParamQueryVO cpProtectionParamQueryVO = new CpProtectionParamQueryVO();
                cpProtectionParamQueryVO.setCpSegmentId(cpSegmentId).setDeviceObject(deviceObject);
                if (StringUtils.isEmpty(deviceItem)) {
                    cpProtectionParamQueryVO.setDeviceItemIsNull(true);
                } else {
                    cpProtectionParamQueryVO.setDeviceItem(deviceItem);
                }
                //根据阴保线路id、设备id和具体参数id得到阴保保护参数集合信息
                List<CpProtectionParamExpandVO> protectionParamExpandVOs = operationPlanMapper.queryParamByQueryVO(cpProtectionParamQueryVO);
                if (protectionParamExpandVOs != null && !protectionParamExpandVOs.isEmpty()) {
                    oldCpProtectionParams.addAll(protectionParamExpandVOs);
                }
            }
            if (!oldCpProtectionParams.isEmpty()) {
                List<JobKey> jobKeys = new ArrayList<JobKey>();//用于保存需要删除的jobKey

                List<String> cpProIds = new ArrayList<String>(); //阴保设施保护参数id集合，用于自定义标准删除信息
                for (int i = 0, len = oldCpProtectionParams.size(); i < len; i++) {
                    CpProtectionParamExpandVO cpProtectionParam = oldCpProtectionParams.get(i);
                    cpProIds.add(cpProtectionParam.getId());
                    if (Objects.equal("20", cpSegment.getDataStated())) { //当线路阴保为已发布的时候，删除原来创建好的阴保计划
                        if (cpProtectionParam.getBeginPlanDate() != null && StringUtils.isNotEmpty(cpProtectionParam.getFrequency())) {
                            JobKey jobKey = getJobKeys(cpProtectionParam, cpSegment.getPipeLineId(), cpSegment.getFromPointId(), cpSegment.getToPointId(), true);
                            if (jobKey != null) {
                                jobKeys.add(jobKey);
                            }
                        }
                    }
                }
                if (!jobKeys.isEmpty()) { //当线路阴保为已发布的时候，删除原来创建好的阴保计划
                    QuartzManagerUtil.removeJob(jobKeys);
                }
                if (!cpProIds.isEmpty()) {
                    operationPlanMapper.deleteCpStandard(cpProIds); //删除自定义标准信息
                    operationPlanMapper.deleteCpProtectionParam(cpSegmentId, cpProIds);
                }
            }

            for (CpProtectionParamExpandVO newParamExpandVO : newParamExpandVOs) {
                String deviceObject = newParamExpandVO.getDeviceObject();
                String deviceParam = newParamExpandVO.getDeviceParam();

                DomainInitUtil.initCreateDomain(newParamExpandVO);
                String proParamId = newParamExpandVO.getId();
                newParamExpandVO.setCpSegmentId(cpSegmentId);
                setDeletedAndNew(newParamExpandVO, 0, 0);
                cpProtectionParamMapper.insertSelective(newParamExpandVO);

                dateVO = newParamExpandVO.getSaveProParamResult();

                if (OperationStandard.CUSTOM.name().equals(cpSegment.getUse())) {
                    CpStandard cpStandard = new CpStandard();
                    DomainInitUtil.initCreateDomain(cpStandard);
                    cpStandard.setProtectionObjectId(proParamId);
                    cpStandard.setDeviceObject(deviceObject);
                    cpStandard.setDeviceItem(deviceParam);
                    cpStandard.setFrequency(newParamExpandVO.getFrequency());
                    setDeletedAndNew(cpStandard, 0, 0);
                    cpStandardMapper.insertSelective(cpStandard);
                }
            }

        } else {
            DomainInitUtil.initCreateDomain(cpSegmentExpandVO);
            cpSegmentExpandVO.setDataStated("03");
            setDeletedAndNew(cpSegmentExpandVO, 0, 0);
            String id = cpSegmentExpandVO.getId();
            cpSegmentMapper.insertSelective(cpSegmentExpandVO);

            List<CpProtectionParamExpandVO> paramExpandVOs = cpSegmentExpandVO.getProParams();
            for (int i = 0, len = paramExpandVOs.size(); i < len; i++) {
                CpProtectionParamExpandVO expandVO = paramExpandVOs.get(i);
                DomainInitUtil.initCreateDomain(expandVO);
                String expandId = expandVO.getId();
                expandVO.setCpSegmentId(id);
                dateVO = expandVO.getSaveProParamResult();
                setDeletedAndNew(expandVO, 0, 0);
                cpProtectionParamMapper.insertSelective(expandVO);

                if (OperationStandard.CUSTOM.name().equals(use)) { //是自定义标准的时候
                    CpStandard cpStandard = new CpStandard();
                    DomainInitUtil.initCreateDomain(cpStandard);
                    cpStandard.setFrequency(expandVO.getFrequency());
                    cpStandard.setName(use);
                    cpStandard.setDeviceObject(expandVO.getDeviceObject());
                    cpStandard.setDeviceItem(expandVO.getDeviceParam());
                    cpStandard.setProtectionObjectId(expandId);

                    setDeletedAndNew(cpStandard, 0, 0);
                    cpStandardMapper.insertSelective(cpStandard);
                }
            }
        }
        return dateVO;
    }

    @Override
    public CpSegment getCpSegment(CpSegment cpSegment) {
        CpSegmentExample example = new CpSegmentExample();
        CpSegmentExample.Criteria criteria = example.createCriteria()
                .andDeletedEqualTo((short) 0).andIsNewestEqualTo((short) 0);
        String id = cpSegment.getId();
        if (StringUtils.isNotEmpty(id)) {
            criteria.andIdEqualTo(id);
        }
        if (Objects.equal(PIPE_LINE_STR, cpSegment.getApplyTo())) {
            criteria.andPipeLineIdEqualTo(cpSegment.getPipeLineId()).andFromPointIdEqualTo(cpSegment.getFromPointId()).andToPointIdEqualTo(cpSegment.getToPointId());
        } else if (Objects.equal(VAVLE_ROOR_STR, cpSegment.getApplyTo())) {
            criteria.andApplyToEqualTo(cpSegment.getApplyTo());
        }
        List<CpSegment> segments = cpSegmentMapper.selectByExample(example);
        return segments.size() == 1 ? segments.get(0) : null;
    }


    @Override
    public CpSegmentExpandVO queryCpSegmentByCondition(CpSegment cpSegment) {
        CpSegment segment = getCpSegment(cpSegment);
        CpSegmentExpandVO cpSegmentExpandVO = new CpSegmentExpandVO();
        if (segment != null) {
            BeanUtils.copyProperties(segment, cpSegmentExpandVO);
            List<CpProtectionParamExpandVO> paramExpandVOs = operationPlanMapper.queryParamByQueryVO(new CpProtectionParamQueryVO().setCpSegmentId(segment.getId()));
            if (!paramExpandVOs.isEmpty()) {
                cpSegmentExpandVO.setProParams(paramExpandVOs);
            }
            return cpSegmentExpandVO;
        }
        return null;
    }

    @Override
    public void queryCrossOverlap(String pipeLineId, Long fromPointMileage, Long toPointMileage) {
        List<CpSegment> cpSegments = operationPlanMapper.queryCrossSegment(pipeLineId, fromPointMileage, toPointMileage);
        if (cpSegments != null && !cpSegments.isEmpty()) {
            CpSegment cpSegment;
            for (int i = 0, len = cpSegments.size(); i < len; i++) {
                cpSegment = cpSegments.get(i);
                Long fromMile = cpSegment.getFromPointMileage();
                Long toMile = cpSegment.getToPointMileage();
                if (fromMile.equals(fromPointMileage) && toMile.equals(toPointMileage)) {
                    continue;
                }
                PipeLocationDTO fromDTO = pipeLocationService.queryPipeLocationById(pipeLineId, cpSegment.getFromPointId());
                PipeLocationDTO toDTO = pipeLocationService.queryPipeLocationById(pipeLineId, cpSegment.getToPointId());

                if (fromDTO != null && toDTO != null) {
                    String fromName = fromDTO.getName();
                    String toName = toDTO.getName();
                    String fromType = fromDTO.getType();
                    String toType = fromDTO.getType();
                    Asserts.assertTrue(1 != 1, fromName + "到" + toName + "段已设置运行计划，请重新选择！"); //给予准确的提示信息
                }
            }
        }
    }

    @Override
    public List<CpSegmentPlanVO> querySegmentPlan(CpSegmentPlanVO cpSegmentPlanVO) {
        List<CpSegmentPlanVO> cpSegmentPlanVOs = operationPlanMapper.querySegmentPlan(cpSegmentPlanVO);
        return cpSegmentPlanVOs;
    }

    @Override
    public void deleteSegmentPlan(String segmentId) {
        CpSegment cpSegment = new CpSegment();
        cpSegment.setId(segmentId);
        CpSegmentExpandVO segment = queryCpSegmentByCondition(cpSegment);
        if (segment != null) {
            List<CpProtectionParamExpandVO> expandVOs = segment.getProParams();
            if (expandVOs != null && !expandVOs.isEmpty()) {
                deleteYBPlan(segment, segment.getDataStated(), expandVOs);
            }
        }
    }

    @Override
    public Map taskCalendar(Date date, String pipeLineId, String fromId, String toId, boolean showValveRoom) {
        CpProtectionParamQueryVO cpProtectionParamQueryVO = new CpProtectionParamQueryVO().setPipeLineId(pipeLineId).setFromId(fromId).setToId(toId).setBeginPlanDateIsNotNull(true);
        List<CpProtectionParamExpandVO> paramExpandVOs = operationPlanMapper.queryParamByQueryVO(cpProtectionParamQueryVO);

        List<JobKey> jobKeys = new ArrayList<JobKey>();

        for (int i = 0, len = paramExpandVOs.size(); i < len; i++) { //查询到对应的管线JobKey
            CpProtectionParamExpandVO paramExpandVO = paramExpandVOs.get(i);
            if (StringUtils.isNotEmpty(paramExpandVO.getFrequency()) && paramExpandVO.getBeginPlanDate() != null) {
                JobKey key = getJobKeys(paramExpandVO, paramExpandVO.getPipeLineId(), paramExpandVO.getFromPointId(), paramExpandVO.getToPointId(), showValveRoom);
                if (key != null)
                    jobKeys.add(key);
            }
        }
        List<Trigger> allTrigger = new ArrayList<Trigger>();
        /*if (showValveRoom) { //需要查询场站阀室的时候
            List<Trigger> valveTriggers = QuartzManagerUtil.getTriggers(CtrlPlanConsts.STANDARD_PLAN_GROUP_NAME + CtrlPlanConsts.VALVE_ROOM_STANDARD_GROUP_NAME);
            if (valveTriggers != null && !valveTriggers.isEmpty()) {
                allTrigger.addAll(valveTriggers);
            }
        }*/

        Trigger trigger;
        for (int i = 0, len = jobKeys.size(); i < len; i++) {//获取管线对应的触发器
            JobKey jobKey = jobKeys.get(i);
            trigger = QuartzManagerUtil.getTrigger(jobKey.getName(), jobKey.getGroup());
            if (trigger != null) {
                allTrigger.add(trigger);
            }
        }

        Table<String, String, Set<String>> tables = HashBasedTable.create();

        for (int i = 0, len = allTrigger.size(); i < len; i++) {
            trigger = allTrigger.get(i);
            JobDataMap jobDataMap = trigger.getJobDataMap();
            Object o = jobDataMap.get(StandardPlan.class.getName());
            if (o != null) {
                List<Date> dates = TaskCalendarUtil.taskTimesBetween(trigger, date);
                StandardPlan standardPlan = (StandardPlan) o;
                String deviceObjectName = standardPlan.getDeviceObjectName();
                String deviceItemName = standardPlan.getDeviceParamName();
                if (dates != null) {
                    for (int j = 0, dSize = dates.size(); j < dSize; j++) {
                        String day = String.valueOf(new LocalDate(dates.get(j)).getDayOfMonth());
                        if (tables.contains(day, deviceObjectName)) {
                            Set<String> strs = tables.get(day, deviceObjectName);
                            if (StringUtils.isNotEmpty(deviceItemName)) {
                                strs.add(deviceItemName);
                            }
                        } else {
                            Set<String> strs = new LinkedHashSet<String>();
                            strs.add(deviceItemName);
                            tables.put(day, deviceObjectName, strs);
                        }
                    }
                }
            }
        }
        Map<String, Map<String, Set<String>>> map = tables.rowMap();
        return map;
    }

    @Override
    public Map getPlans() {
        String pipeLineId = null;
        String fromId = null;
        String toId = null;
        CpProtectionParamQueryVO cpProtectionParamQueryVO = new CpProtectionParamQueryVO().setPipeLineId(pipeLineId).setFromId(fromId).setToId(toId).setBeginPlanDateIsNotNull(true);
        List<CpProtectionParamExpandVO> paramExpandVOs = operationPlanMapper.queryParamByQueryVO(cpProtectionParamQueryVO);

        List<ScheduleDto> listMap = new ArrayList<ScheduleDto>();
        Map<String, Object> mapResult = new HashMap<String, Object>();
        Trigger trigger;
        for (int i = 0, len = paramExpandVOs.size(); i < len; i++) { //查询到对应的管线JobKey
            CpProtectionParamExpandVO paramExpandVO = paramExpandVOs.get(i);
            if (StringUtils.isNotEmpty(paramExpandVO.getFrequency()) && paramExpandVO.getBeginPlanDate() != null) {
                JobKey key = getJobKeys(paramExpandVO, paramExpandVO.getPipeLineId(), paramExpandVO.getFromPointId(), paramExpandVO.getToPointId(), true);
                if (key != null) {
                    trigger = QuartzManagerUtil.getTrigger(key.getName(), key.getGroup());
                    if (trigger != null) {
                        ScheduleDto scheduleDto = new ScheduleDto();
                        JobDataMap jobDataMap = trigger.getJobDataMap();
                        Object o = jobDataMap.get(StandardPlan.class.getName());
                        StandardPlan standardPlan = (StandardPlan) o;
                        BeanUtils.copyProperties(standardPlan,scheduleDto);//COPY属性
                        scheduleDto.setStartTime(LocalDate.fromDateFields(trigger.getStartTime()).toDate());
                        scheduleDto.setEndTime(trigger.getEndTime());
                        if (o instanceof PipeLineStandard) {
                            //其实这里都不用判断了，只不过我定义的fromMileage,而肖总写的是fromPointMilage.
                            PipeLineStandard pipeLineStandard = (PipeLineStandard) o;
                            //BeanUtils.copyProperties(pipeLineStandard,scheduleDto);
                            scheduleDto.setFromMileage(pipeLineStandard.getFromPointMileage());
                            scheduleDto.setToMileage(pipeLineStandard.getToPointMileage());

                            PipeLineElementExample example = new PipeLineElementExample();
                            example.createCriteria().andPipeLineIdEqualTo(scheduleDto.getPipeLineId())
                                    .andElementIdEqualTo(scheduleDto.getFromPointId()).andDeletedEqualTo((short)0);
                            List<PipeLineElement> fromElements = pipeLineElementMapper.selectByExample(example);

                            example.createCriteria().andPipeLineIdEqualTo(scheduleDto.getPipeLineId())
                                    .andElementIdEqualTo(scheduleDto.getToPointId()).andDeletedEqualTo((short)0);
                            List<PipeLineElement> toElements = pipeLineElementMapper.selectByExample(example);

                            scheduleDto.setFromName(fromElements.get(0).getElementName());
                            scheduleDto.setToName(toElements.get(0).getElementName());
                        }
                        listMap.add(scheduleDto);
                    }
                }
            }
        }
        if (ObjectUtil.isNotNullEmpty(listMap)) {
            mapResult.put("List", listMap);
        }
        return mapResult;
    }
}
